﻿using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace BodyFatCalculator
{

    public class CheckedToEnabledConverter : IMultiValueConverter
    {
        public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool lanyKivalasztva = (bool)value[0];
            bool amcsiKivalasztva = (bool)value[1];
            return lanyKivalasztva && amcsiKivalasztva;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


    [Serializable]
    public class MeretAdatok
    {

        #region Constructors

        /// <summary>
        /// default constructor, a serializálás miatt kell
        /// </summary>
        public MeretAdatok() { }

        public MeretAdatok(string email, string nem, Int32 eletkor, Int32 testMagassag, Int32 testSuly, Int32 derekMeret, Int32 csipoMeret, Int32 nyakMeret, Int32 testZsirSzazalek, string bmi)
        {
            this.email = email;
            this.nem = nem;
            this.eletkor = eletkor;
            this.testMagassag = testMagassag;
            this.testSuly = testSuly;
            this.derekMeret = derekMeret;
            this.csipoMeret = csipoMeret;
            this.nyakMeret = nyakMeret;
            this.testZsirSzazalek = testZsirSzazalek;
            this.bmi = bmi;
        }

        #endregion

        public String email { get; set; }

        public String nem { get; set; }

        public Int32 eletkor { get; set; }

        public Int32 testMagassag { get; set; }

        public Int32 testSuly { get; set; }

        public Int32 derekMeret { get; set; }

        public Int32 csipoMeret { get; set; }

        public Int32 nyakMeret { get; set; }

        public Int32 testZsirSzazalek { get; set; }

        public String bmi { get; set; }

    }


    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        string XMLfile = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\BodyFatCalculator.xml";

        public MainWindow()
        {
            InitializeComponent();

            if (File.Exists(XMLfile))
            {
                MemoryStream m = new MemoryStream();
                XML2m(ref m);

                string postData = Encoding.ASCII.GetString(m.ToArray());
                if (adatFeltoltes(postData))
                {
                    delXML();
                }
            }
        }

        private enum kategoria
        {
            sovány = 1,
            egészséges = 2,
            túlsúlyos = 3,
            elhízott = 4
        }

        private enum hatterszin
        {
            White = kategoria.sovány,
            LightGray = kategoria.egészséges,
            Gray = kategoria.túlsúlyos,
            Black = kategoria.elhízott
        }

        private enum betuszin
        {
            Blue = kategoria.sovány,
            Green = kategoria.egészséges,
            Yellow = kategoria.túlsúlyos,
            Red = kategoria.elhízott
        }

        private enum nemek
        {
            lany = 1,
            fiu = 0
        }

        private int[][] testZsirCsoportNo = new int[4][] { new int[2] { 39, 59 }, new int[3] { 21, 33, 39 }, new int[3] { 23, 34, 40 }, new int[3] { 24, 35, 42 } };
        private int[][] testZsirCsoportFerfi = new int[4][] { new int[2] { 39, 59 }, new int[3] { 8, 20, 25 }, new int[3] { 11, 22, 28 }, new int[3] { 13, 25, 30 } };
        private double[] bmiCsoport = new double[4] { 18.5, 24.9, 29.9, 30 };

        private int ymca(double allando, double derekMeret, double testSuly)
        {
            double eredmeny = 0;
            eredmeny = ((allando + (4.15 * (derekMeret / 2.54)) - (0.082 * (testSuly * 2.20462262185))) / (testSuly * 2.20462262185)) * 100;
            return (int)eredmeny;
        }

        private int amcsi(double allando1, double allando2, double allando3, double testMagassag, double derekMeret, double csipoMeret, double nyakMeret)
        {
            double eredmeny = 0;
            double log1 = Math.Log10(derekMeret + csipoMeret - nyakMeret);
            double log2 = Math.Log10(testMagassag);
            eredmeny = (495 / (allando1 - (allando2 * log1) + (allando3 * log2))) - 450;
            return (int)eredmeny;
        }

        private double bmiSzamolas(double testMagassag, double testSuly)
        {
            double eredmeny = 0;
            testMagassag /= 100;

            if (bmi_normal.IsChecked == true)
            {                
                eredmeny = (testSuly / (testMagassag * testMagassag));
            }
            else
            {
                eredmeny = (testSuly * 1.3) / (testMagassag * 2.5);
            }

            return eredmeny;
        }

        private bool szamol()
        {            
            bool hiba = false;
            int kor = 0;
            int testZsirSzazalek = 0;
            double testMagassag = 0;
            double derekMeret = 0;
            double csipoMeret = 0;
            double testSuly = 0;
            double nyakMeret = 0;
            string nem = ((nemek)((lany.IsChecked == true) ? 1 : 0)).ToString();

            double allando1;
            double allando2;
            double allando3;
            double allando4;

            if (!Regex.IsMatch(email.Text, @"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$"))
            {
                email.Text = "Hibás email cím!";
                hiba = true;
            }

            if (!int.TryParse(eletkor.Text, out kor))
            {
                eletkor.Text = "Hibás érték!";
                hiba = true;
            }

            if (!Double.TryParse(magassag.Text, out testMagassag))
            {
                magassag.Text = "Hibás érték!";
                hiba = true;
            }

            if (!Double.TryParse(suly.Text, out testSuly))
            {
                suly.Text = "Hibás érték!";
                hiba = true;
            }

            if (!Double.TryParse(derek.Text, out derekMeret))
            {
                derek.Text = "Hibás érték!";
                hiba = true;
            }
            
            if (lany.IsChecked == true) // lányok
            {
                if (amcsi_modszer.IsChecked == true)
                {
                    if (!Double.TryParse(csipo.Text, out csipoMeret))
                    {
                        csipo.Text = "Hibás érték!";
                        hiba = true;
                    }
                    if (!hiba)
                    {
                        csipoDerekArany.Text = (derekMeret / csipoMeret).ToString("0.00");
                    }
                }
                allando1 = -76.76;
                allando2 = 1.29579;
                allando3 = 0.35004;
                allando4 = 0.221;
            }
            else                        // fiúk
            {
                allando1 = -98.42;
                allando2 = 1.0324;
                allando3 = 0.19077;
                allando4 = 0.15456;
            }

            if (ymca_modszer.IsChecked == true) // YMCA módszer
            {
                if (hiba)
                {
                    return false;
                }
                testZsirSzazalek = ymca(allando1, derekMeret, testSuly);
            }
            else                                // US Navy módszer
            {                
                if (!Double.TryParse(nyak.Text, out nyakMeret))
                {
                    nyak.Text = "Hibás érték!";
                    hiba = true;
                }
                if (hiba)
                {
                    return false;
                }

                testZsirSzazalek = amcsi(allando2, allando3, allando4, testMagassag, derekMeret, csipoMeret, nyakMeret);
            }

            if ((testZsirSzazalek < 2) || (testZsirSzazalek > 75))
            {
                testzsir.Background = Brushes.White;
                testzsir.Foreground = Brushes.Red;
                testzsir.Text = "Hibás adatok kerültek megadásra!";
                return false;
            }

            double bmi = bmiSzamolas(testMagassag, testSuly);
            testzsir.Text = testZsirSzazalek.ToString() + " - " + diagnozis(kor, testZsirSzazalek);
            string bmiText = bmi.ToString("F2");
            bmiTextBox.Text = bmiText + " - " + bmiDiagnozis(bmi);

            MeretAdatok meretek = new MeretAdatok(email.Text.ToLower(), nem, kor, (int)testMagassag, (int)testSuly, (int)derekMeret, (int)csipoMeret, (int)nyakMeret, testZsirSzazalek, bmiText);
            List<MeretAdatok> meretLista = new List<MeretAdatok>();
            meretLista.Add(meretek);
            
            XmlSerializer serializer = new XmlSerializer(typeof(List<MeretAdatok>));
            MemoryStream m = new MemoryStream();
            serializer.Serialize(m, meretLista);

            string postData = Encoding.ASCII.GetString(m.ToArray());

            if (!adatFeltoltes(postData))
            {
                meret2XML(meretek);
            }
            
            return true;
        }

        private bool delXML()
        {
            try
            {
                File.Delete(XMLfile);
            }
            catch
            {
                return false;
            }
            return true;
        }

        private bool XML2m(ref MemoryStream m)
        {
            try
            {
                using (FileStream fileStream = File.OpenRead(XMLfile))
                {
                    m.SetLength(fileStream.Length);
                    fileStream.Read(m.GetBuffer(), 0, (int)fileStream.Length);
                }
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        private List<MeretAdatok> XML2meretek()
        {
            List<MeretAdatok> meretLista = new List<MeretAdatok>();
            try
            {
                XmlSerializer serializer;
                TextReader ReadFileStream;
                ReadFileStream = new StreamReader(XMLfile, false);
                serializer = new XmlSerializer(typeof(List<MeretAdatok>));

                MeretAdatok meretek = new MeretAdatok();
                
                meretLista = (List<MeretAdatok>)serializer.Deserialize(ReadFileStream);
                ReadFileStream.Close();
            }
            catch
            {
                meretLista.Clear();
            }
            return meretLista;
        }

        private bool meret2XML(MeretAdatok meretek)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(List<MeretAdatok>));
                TextWriter WriteFileStream;
                List<MeretAdatok> meretLista = new List<MeretAdatok>();

                if (File.Exists(XMLfile))
                {
                    meretLista = XML2meretek();
                    meretLista.Add(meretek);
                }
                else
                {
                    meretLista.Add(meretek);
                }

                WriteFileStream = new StreamWriter(XMLfile, false);
                serializer.Serialize(WriteFileStream, meretLista);
                WriteFileStream.Close();
            }
            catch
            {
                return false;
            }
            return true;
        }

        private string bmiDiagnozis(double bmi)
        {
            int bmiCsop = 0;
            foreach (double b in bmiCsoport)
            {
                bmiCsop++;
                if (bmi <= b)
                {
                    break;
                }
            }

            bmiTextBox.Background = (Brush)new BrushConverter().ConvertFromString(((hatterszin)(kategoria)bmiCsop).ToString());
            bmiTextBox.Foreground = (Brush)new BrushConverter().ConvertFromString(((betuszin)(kategoria)bmiCsop).ToString());

            return ((kategoria)bmiCsop).ToString();
        }

        private string diagnozis(int kor, int testZsirSzazalek)
        {
            string diag = "";
            int korCsoport = 1;
            int sulyCsoport = 1;

            foreach (int k in testZsirCsoportNo[0])
            {
                if (kor <= k)
                {
                    break;
                }
                korCsoport++;
            }

            foreach (int cs in testZsirCsoportNo[korCsoport])
            {
                sulyCsoport++;
                if (testZsirSzazalek <= cs)
                {
                    sulyCsoport--;
                    break;
                }
            }

            diag = ((kategoria)sulyCsoport).ToString();
            testzsir.Background = (Brush)new BrushConverter().ConvertFromString(((hatterszin)(kategoria)sulyCsoport).ToString());
            testzsir.Foreground = (Brush)new BrushConverter().ConvertFromString(((betuszin)(kategoria)sulyCsoport).ToString());            

/*          Hogy is épül fel a háttér + betűszín?

            string szin = ((hatterszin)(kategoria)sulyCsoport).ToString();            
            Brush b = (Brush)new BrushConverter().ConvertFromString(szin);
            testzsir.Background = b;
 
*/
            return diag;
        }

        private void ClearTextBoxes(DependencyObject obj)
        {
            TextBox tb = obj as TextBox;
            if ((tb != null) && (!tb.Equals(figyelmeztetoSzoveg)) && (!tb.Equals(elfogadSzoveg)))
                tb.Text = string.Empty;

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj as DependencyObject); i++)
                ClearTextBoxes(VisualTreeHelper.GetChild(obj, i));
        }
        
        private void btnSzamol_Click(object sender, RoutedEventArgs e)
        {
            if (!btnSzamol.Content.Equals("Számol"))
            {
                testzsir.Background = Brushes.White;
                csipoDerekArany.Text = null;
                ClearTextBoxes(this);
                btnSzamol.Content = "Számol";
                return;
            }
            else
            {
                szamol();
                btnSzamol.Content = "Új számítás";
            }
        }

        private void btnKilep_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private bool adatFeltoltes(string postData)
        {
            bool feltoltve = false;
            try
            {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://athis-test.appspot.com/UploadBFC");
//                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://localhost:8080/UploadBFC");
//                myRequest.SendChunked = true;
                ASCIIEncoding encoding = new ASCIIEncoding();
                myRequest.Method = "POST";
                myRequest.ContentType = "text/xml; encoding='utf-8'";

                byte[] byteArray = Encoding.ASCII.GetBytes(postData);
                myRequest.ContentLength = byteArray.Length;

                Stream dataStream = myRequest.GetRequestStream();
                dataStream.Write(byteArray, 0, byteArray.Length);
                dataStream.Flush();
                dataStream.Close();

                WebResponse response = (HttpWebResponse)myRequest.GetResponse();

/*
                using (Stream stream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    String responseString = reader.ReadToEnd();
                }
*/
//                string msg = ((HttpWebResponse)response).StatusDescription;
                int code = (int)((HttpWebResponse)response).StatusCode;
                response.Close();

                if (code == 200)
                {
                    feltoltve = true;
                }
            }
            catch (WebException ex) { }
            catch (Exception e) { }
            return feltoltve;
        }

        private void btnLekerdez_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start("http://athis-test.appspot.com/QueryBFC");
            }
            catch { }
        }

    }

}
